﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.IO;

namespace LaunchMeNot.Core {
    /// <summary>
    /// A program which runs at startup.
    /// </summary>
    public class StartupEntryBase : IStartupEntry, INotifyPropertyChanged {
        protected string _name,
                         _path,
                         _arguments = string.Empty;
        protected StartupEntryType _entryType;

        /// <summary>
        /// Gets or sets the type of the entry.
        /// </summary>
        /// <value>The type of the entry.</value>
        public virtual StartupEntryType EntryType
        {
            get { return _entryType; }
            set
            {
                _entryType = value;
                OnPropertyChanged("EntryType");
            }
        }

        public virtual string Name {
            get { return _name; }
            set {
                _name = value;
                OnPropertyChanged("Name");
            }
        }

        /// <summary>
        /// Gets or sets the path to the item to launch.
        /// </summary>
        /// <value>The path to the item to launch.</value>
        public virtual string Path {
            get { return _path; }
            set {
                _path = value;
                OnPropertyChanged("Path");
            }
        }

        public string SafeFullPath
        {
            get
            {
                if (Path == null)
                    return string.Empty;
                return (Path.StartsWith("\"") ? string.Empty : "\"") +
                        Path +
                       (Path.EndsWith("\"") ? string.Empty : "\"") +
                       (string.IsNullOrEmpty(Arguments) ? string.Empty : " " + Arguments.Trim());
            }
        }

        /// <summary>
        /// Gets or sets the arguments to pass to the program on launch.
        /// </summary>
        /// <value>The arguments to pass to the program on launch.</value>
        public virtual string Arguments
        {
            get { return _arguments; }
            set
            {
                _arguments = value;
                OnPropertyChanged("Arguments");
            }
        }

        /// <summary>
        /// Gets the full path including arguments.
        /// </summary>
        /// <value>The full path including arguments.</value>
        public virtual string FullPath
        {
            get { return Path.Trim() + (string.IsNullOrEmpty(Arguments) ? string.Empty : (" " + Arguments.Trim())); }
        }

        public StartupEntryBase() {
            this.Name = string.Empty;
            this.Path = string.Empty;
            this.Arguments = string.Empty;
        }

        /// <summary>
        /// Initializes a new <see cref="StartupEntryBase"/> from an existing file path.
        /// </summary>
        /// <param name="fileName">Full path of the file.</param>
        public StartupEntryBase(string fileName) 
            :this() {
                if (File.Exists(fileName)) {
                    this.Name = System.IO.Path.GetFileNameWithoutExtension(fileName);
                    var pair = Utils.SplitArguments(fileName);
                    this.Path = pair.Key;
                    this.Arguments = pair.Value;
                } else {
                    this.Path = fileName;
                }
        }

        public StartupEntryBase(string name, string path, string arguments)
            : this() {
            this.Name = name;
            this.Path = path;
            this.Arguments = arguments;
        }

        /// <summary>
        /// Initializes a new <see cref="StartupEntryBase"/> from an existing entry.
        /// </summary>
        /// <param name="entry">The entry.</param>
        public StartupEntryBase(IStartupEntry entry) 
            :this() {
            this.Arguments = entry.Arguments;
            this.Name = entry.Name;
            this.Path = entry.Path;
        }

        /// <summary>
        /// Clones this instance.
        /// </summary>
        /// <returns>A deep copy of this entry.</returns>
        public virtual IStartupEntry Clone()
        {
            var entry = new LaunchMeNotEntry()
            {
                Name = this.Name,
                Path = this.Path,
                Arguments = this.Arguments
            };
            return entry;
        }


        public override string ToString()
        {
            return string.Format("{0} - {1}{2}", Name ?? string.Empty, Path ?? string.Empty, Arguments ?? string.Empty);
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string strPropertyName) {
            if (PropertyChanged != null) {
                PropertyChanged(this, new PropertyChangedEventArgs(strPropertyName));
            }
        }
    }
}